package com.azt.front.service.impl;

import com.azt.api.pojo.Company;
import com.azt.api.pojo.LoginLog;
import com.azt.api.pojo.Role;
import com.azt.api.pojo.User;
import com.azt.api.service.MsgConfigService;
import com.azt.api.service.UserPermissionService;
import com.azt.api.service.UserService;
import com.azt.front.service.UserFrontService;
import com.azt.front.utils.ContextUtil;
import com.azt.model.FrontGlobals;
import com.azt.model.IforgotConstant;
import com.azt.model.VerifyCode;
import com.azt.provider.mapper.CompanyMapper;
import com.azt.utils.CommonUtil;
import com.azt.utils.CookieUtils;
import com.xiaoleilu.hutool.date.DateField;
import com.xiaoleilu.hutool.date.DateUtil;
import com.xiaoleilu.hutool.util.CollectionUtil;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class UserFrontServiceImpl implements UserFrontService {

    private static final Logger LOGGER = Logger.getLogger(UserFrontServiceImpl.class);

    @Autowired
    private CompanyMapper companyMapper;

    @Autowired
    private UserPermissionService userPermissionService;

    @Autowired
    private UserService userService;

    @Autowired
    private MsgConfigService msgConfigService;

    /**
     * 加入登录相关的session、cookie
     * @param user 用户信息
     * @param username 用户登录时输入的用户名
     * @param rememberMe 是否记住我
     * */
    @Override
    public void recordLoginSessionAndCookie(User user, int loginType, String username, boolean rememberMe, Integer currentRoleId) {
        recordLoginInfo(user, loginType, true, username, rememberMe, currentRoleId);
    }

    /**
     * 加入登录相关的session，不记录cookie，用于自动登录
     * @param user 用户信息
     * */
    @Override
    public void recordLoginSession(User user, int loginType, Integer currentRoleId) {
        recordLoginInfo(user, loginType, false, null, false, currentRoleId);
    }

    private void recordLoginInfo(User user, int loginType, boolean recordCookie, String username, boolean rememberMe, Integer currentRoleId) {
        //为user注入company和role信息
        if(user.getCompanyId() != null && user.getCompany() == null) {
            Company company = companyMapper.selectByPrimaryKey(user.getCompanyId());
            user.setCompany(company);
        }
        List<Role> roleList = userPermissionService.findRoleByUserId(user.getId());		//该用户所属的角色
        user.setRoles(roleList);

        //记录session
        ContextUtil.getSession().setAttribute(FrontGlobals.CURRENT_USER, user);		//用户信息
        ContextUtil.getSession().setAttribute(FrontGlobals.LOGIN_TYPE, loginType);		//登录类型
        if(currentRoleId != null) {
            Role role = userPermissionService.getRoleById(currentRoleId);
            if(role != null) {
                ContextUtil.getSession().setAttribute(FrontGlobals.CURRENT_ROLE, role);	//当前以什么角色登录
            } else {
                if(roleList != null && roleList.size() > 0) {
                    ContextUtil.getSession().setAttribute(FrontGlobals.CURRENT_ROLE, roleList.get(0));	//当前以什么角色登录
                }
            }
        } else {
            if(roleList != null && roleList.size() > 0) {
                ContextUtil.getSession().setAttribute(FrontGlobals.CURRENT_ROLE, roleList.get(0));	//当前以什么角色登录
            }
        }

        if(recordCookie) {
            //记录登录cookie
            if(rememberMe) {
                ContextUtil.setRememberMeLoginCookie(user.getId(), username, (CollectionUtil.isNotEmpty(roleList) ? roleList.get(0).getId() : 0), user.getSalt());
            } else {
                ContextUtil.setCommonLoginCookie(user.getId(), username, (CollectionUtil.isNotEmpty(roleList) ?roleList.get(0).getId() : 0), user.getSalt());
            }
        }

        //记录登录日志
        if(userService.getLoginLog(ContextUtil.getSession().getId(), user.getId()) == null) {
            LoginLog loginLog = new LoginLog();
            loginLog.setIp(CommonUtil.getIp(ContextUtil.getRequest()));
            loginLog.setSessionId(ContextUtil.getSession().getId());
            loginLog.setUserId(user.getId());
            loginLog.setLoginType(loginType);
            loginLog.setLoginTime(new Date());
            loginLog.setExpireTime(rememberMe ? DateUtil.offset(new Date(), DateField.SECOND, FrontGlobals.REMEMBERME_COOKIE_EXPIRE) : new Date());
            userService.insertLoginLog(loginLog);
        }

        //重置sessionId，原session中的数据自动保存到新的session中
        //CommonUtil.resetSessionId(ContextUtil.getRequest());
    }

    /**
     * 找回密码：发送短信验证码
     * */
    @Override
    public void sendIforgotSMS(HttpServletRequest request, HttpServletResponse response, String mobile) {
        //发送短信验证码
        String smsCode = RandomStringUtils.randomNumeric(6);
        LOGGER.info("iforgot sms code:" + smsCode);
        request.getSession().setAttribute(IforgotConstant.SMS_SESSION, new VerifyCode(smsCode, new Date(),
                DateUtils.addMinutes(new Date(), IforgotConstant.SMS_EXPIRE)));

        Map<String, String> msgParam = new HashMap<>();
        msgParam.put("code", smsCode);
        msgParam.put("time", IforgotConstant.SMS_EXPIRE + "");
        msgConfigService.sendMessageWithOutUserId("IFORGOT_SMS", msgParam, mobile, null, false);

        //生成短信验证码倒计时cookie
        CookieUtils.setCookie(request, response, IforgotConstant.SMS_COOKIE, "60");
    }

    /**
     * 注册：发送短信验证码
     * */
    @Override
    public void sendRegisterSMS(HttpServletRequest request, HttpServletResponse response, String mobile) {
        //发送短信验证码
        String smsCode = RandomStringUtils.randomNumeric(6);
        LOGGER.info("register sms code:" + smsCode);
        request.getSession().setAttribute(FrontGlobals.REGISTER_SMS_SESSION,
                new VerifyCode(smsCode, new Date(), DateUtils.addMinutes(new Date(), FrontGlobals.REGISTER_SMS_EXPIRE)));

        Map<String, String> msgParam = new HashMap<>();
        msgParam.put("code", smsCode);
        msgParam.put("time", FrontGlobals.REGISTER_SMS_EXPIRE + "");
        msgConfigService.sendMessageWithOutUserId("REGISTER_SMS", msgParam, mobile, null, false);

        //生成短信验证码倒计时cookie
        CookieUtils.setCookie(request, response, FrontGlobals.REGISTER_SMS_COOKIE, "60");
    }

    /**
     * 判断是否是合法的找回密码请求，防止越权操作
     * */
    @Override
    public boolean isValidIforgotRequest(HttpServletRequest request, Integer step) {
        User user = (User)request.getSession().getAttribute(IforgotConstant.USER_SESSION);
        Integer _step = CommonUtil.safeToInteger(request.getSession().getAttribute(IforgotConstant.STEP_SESSION));
        String type = CommonUtil.safeToString(request.getSession().getAttribute(IforgotConstant.TYPE_SESSION));
        if(user != null && StringUtils.isNotBlank(type) && ("email".equals(type) || "mobile".equals(type))) {
            if(step == null || step.equals(_step)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void logout() {
        HttpServletRequest request = ContextUtil.getRequest();
        HttpServletResponse response = ContextUtil.getResponse();

        String sessionId = request.getSession().getId();
        Integer userId = ContextUtil.getUserId();

        request.getSession().removeAttribute(FrontGlobals.CURRENT_USER);
        request.getSession().removeAttribute(FrontGlobals.CURRENT_ROLE);
        request.getSession().removeAttribute(FrontGlobals.LOGIN_TYPE);
        CookieUtils.deleteCookie(request, response, FrontGlobals.LOGIN_COOKIE_NAME);

        //记录退出时间
        if(userId != null) {
            LoginLog loginLog = userService.getLoginLog(sessionId, userId);
            if (loginLog != null) {
                loginLog.setExitTime(new Date());
                userService.updateLoginLog(loginLog);
            }

            //改变sessionId
            CommonUtil.resetSessionId(request);
        }
    }
}
